package Question;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 解决Java Collectors.toMap 方法 value为null不支持的问题
 * 问题场景：
 * 需要将List转换为Map时，通常会用到Collectors.toMap方法转换,但是当转换后的Value有null时，会抛出空指针异常
 * 异常：
 * java.lang.NullPointerException
 * at java.util.HashMap.merge(HashMap.java:1225)
 * <p>
 * 参考：
 * https://blog.csdn.net/weixin_48990070/article/details/125428557
 * @Author: LiuZiHao
 * @Date: 2022/7/5 17:38
 */
public class CollectorToMap {
    static class Data {
        int key;
        String value;

        public Data(int key, String value) {
            this.key = key;
            this.value = value;
        }
    }

    @Test
    public void test_toMap() {
        List<Data> dataList = new ArrayList<>();
        dataList.add(new Data(1, "A"));
        dataList.add(new Data(2, "B"));
        dataList.add(new Data(3, "C"));
        dataList.add(new Data(4, null));
        dataList.add(new Data(5, null));
        Map<Integer, String> dataMap = dataList.stream().collect(Collectors.toMap(item -> item.key, item -> item.value));
        //原因：省略


    }
    //解决方案：

    //实现方案 1 使用Collectors.groupingBy
    @Test
    public void test_groupByMap() {
        List<Data> dataList = new ArrayList<>();
        dataList.add(new Data(1, "A"));
        dataList.add(new Data(2, "B"));
        dataList.add(new Data(3, "C"));
        dataList.add(new Data(4, null));
        dataList.add(new Data(5, null));
        Map<Integer, String> dataMap = dataList.stream()
                .collect(Collectors.groupingBy(item -> item.key,
                        HashMap::new,
                        Collectors.reducing(null, item -> item.value, (v1, v2) -> v2)
                        )
                );
        System.out.println("===============================");
        for (Map.Entry<Integer, String> entry : dataMap.entrySet()) {
            System.out.println("key = " + entry.getKey() + " and value = " + entry.getValue());
        }
    }

    //实现方案 2 使用Collectors.groupingBy
    @Test
    public void test_putAll() {
        List<Data> dataList = new ArrayList<>();
        dataList.add(new Data(1, "A"));
        dataList.add(new Data(2, "B"));
        dataList.add(new Data(3, "C"));
        dataList.add(new Data(4, null));
        dataList.add(new Data(5, null));
        Map<Integer, String> dataMap = dataList.stream()
                .collect(HashMap::new, (map, item) -> map.put(item.key, item.value), (map1, map2) -> map1.putAll(map2)
                );
        System.out.println("===============================");
        for (Map.Entry<Integer, String> entry : dataMap.entrySet()) {
            System.out.println("key = " + entry.getKey() + " and value = " + entry.getValue());
        }
    }

}
